#include "pool.h"

using std::cout;

Pool::Pool(size_t elemSize, size_t blockSize = 5, bool traceFlag = false)
	: blockSize(blockSize), elemSize(elemSize), traceFlag(traceFlag)
{
	RowCount = 0;
	grow();
}

Pool::~Pool()
{
	if (traceFlag == true)
		cout << "\nDeleting " << RowCount << " rows from the pool.";
	for (size_t i = 0; i < RowCount; ++i)
		delete [] pool[i]; //ToDo: have a bug here not sure what is wrong with it.
	delete [] pool;
}

void* Pool::allocate()
{
	if (traceFlag == true)
	{
		cout << "\nAllocating memory from the pool at ";
		//cout << static_cast<void*>(head);
	}

	if (head == 0)
		grow();

	void* tmp = head;
	head = getFromBucket(static_cast<char*>(head));
	return tmp;
}

void Pool::deallocate(void* v_ptr)
{
	if (traceFlag == true)
		cout << "\nDeallocating memory and giving it back to the pool.";
	char* to = static_cast<char*>(v_ptr);
	putInBucket(to, static_cast<char*>(head)); 
	head = to;
}

void Pool::grow()
{
	if (traceFlag == true)
		cout << "\nGrowing the pool.";
	char** tmpPool;
	tmpPool = new char*[RowCount+1]; //Create new row

	if (pool)
	{
		for (unsigned int i = 0; i < RowCount - 1; i++)
		{
			tmpPool[i] = pool[i];
		}
		delete [] pool; // cleanup old pool before pointing to the new destination
	}
	pool = tmpPool;

	pool[RowCount] = new char[blockSize * elemSize];

	size_t count = elemSize;
	for (size_t i = 0; i < count - 1; i ++)
	{
		char * tmp = pool[RowCount] + (i * elemSize);
		putInBucket(tmp, tmp + elemSize);
	}
	char * end = pool[RowCount] + elemSize * (count - 1);
	putInBucket(end, 0);

	head = pool[RowCount++]; // move the head to the new row
}